package com.dkasza.qicky;

import java.io.*;

/** Request handler to handle static files.
 *  This request handler should be used when an HttpServer needs to handle static
 *  files.
 */
public class HttpStaticRequestHandler implements HttpRequestHandler {

    /** Main constructor for the class.
     *
     * @param pref the prefix for the URI.
     * @param path absolute or relative path to the working directory of this class.
     * @param default URI of the default document
     */
    public HttpStaticRequestHandler(String pref, String path, String defaultDoc) {
        if(!(pref.endsWith("\\") || pref.endsWith("/"))) {
            pref += '/';
        }
        prefixString = pref;
        if(!(path.endsWith("\\") || path.endsWith("/"))) {
            path += '/';
        }
        directory = path;
        defaultDocument = defaultDoc;
    }

    private String prefixString;
    /**
     * Absolute or relative path to the working (shared) directory.
     */
    public  String directory;
    /**
     * URI of the default document (/)
     */
    public  String defaultDocument;
    private final int BUFFER_SIZE = 65536;
    /**
     * The server will tell the client not to download the same file again for
     * this many seconds.
     */
    public long cacheControl = 3600;
    
    @Override
    public String prefix() {
        return prefixString;
    }

    @Override
    public Http.Response handler(Http.Request req) {
        // no post support of course
        if(req.method.equals("post")) {
            
            return new Http.Response(false, req.messages.headerNotImplemented+'\n'+req.messages.msgNotImplemented+'\n');
        }
        
        
        if(req.path.contains("..")) { // if someone's trying to leave the working directory
            // then say that it was a bad request
            // this is not keep-alive safe
            return new Http.Response(false, req.messages.headerBadRequest + '\n' + req.messages.msgBadRequest);
        }
        if(req.path.equals(prefixString)) { //requesting the default document
            req.path = defaultDocument;
        } else {
            req.path = req.path.substring(prefixString.length());
        }
        try(FileInputStream in = new FileInputStream(directory+req.path)) {
            File file = new File(directory+req.path);
            // assemble the response header
            String responseHeader = req.messages.headerOK+
                    req.messages.headerCacheControl(3600) + 
                    req.messages.headerContentLength(file.length()) + 
                    req.messages.headerKeepAlive + '\n';
            // send the header
            req.socket.getOutputStream().write(responseHeader.getBytes());
            
            if(req.method.equals("get")) { // if the client requested a download
                // create a buffer for sending the file
                byte[] buff = new byte[BUFFER_SIZE];
                int read;
                while((read = in.read(buff)) > 0) {
                    req.socket.getOutputStream().write(buff, 0, read);
                }
            }
            //and we are done
            return new Http.Response(true, ""); // we did all the writing ourselves
        } catch(IOException ioe) {
            /* TODO: better exception handling
             * Now we just assume that the file was not found
             * This is not keep-alive-safe of course
             */
            return new Http.Response(false, req.messages.headerNotFound+'\n'+req.messages.msgNotFound);
        }
    }
    
}
